module ysyx_22040213_EXEReg(
	input clk,
	input rst,
	input flush,

	input ID_to_EXE_valid,
	input EXE_ready_go,
	input MEM_allow_in,

	output EXE_allow_in,
	output EXE_to_MEM_valid,


	input [3:0] i_exe_AluData1_en,
	input [6:0] i_exe_AluData2_en,
	input [63:0] i_exe_src1,
	input [63:0] i_exe_src2,
	input [63:0] i_exe_ext_imm,
	input [63:0] i_exe_pc_link,
	input [63:0] i_exe_shamt,
	input [16:0] i_exe_alu_op,
	input [2:0] i_exe_funct3,
	input [4:0] i_exe_rd,
	input i_exe_w_en,
	input i_exe_word_en,
	input i_exe_sm_en,
	input i_exe_lm_en,
	input [3:0] i_exe_RegWrite_en,
	input [63:0] i_exe_csr_src1,

	output [3:0] o_exe_AluData1_en,
	output [6:0] o_exe_AluData2_en,
	output [63:0] o_exe_src1,
	output [63:0] o_exe_src2,
	output [63:0] o_exe_ext_imm,
	output [63:0] o_exe_pc_link,
	output [63:0] o_exe_shamt,
	output [16:0] o_exe_alu_op,
	output [2:0] o_exe_funct3,
	output [4:0] o_exe_rd,
	output o_exe_w_en,
	output o_exe_word_en,
	output o_exe_lm_en,
	output o_exe_sm_en,
	output [3:0] o_exe_RegWrite_en,
	output [63:0] o_exe_csr_src1,
	output o_exe_reg_w_en,

	//for difftest//
	input [31:0] i_exe_inst,
	input [63:0] i_exe_dnpc,
	input i_exe_id_bubble,
	input i_exe_exe_bubble,
	input i_exe_clint_trap,

	output [31:0] o_exe_inst,
	output [63:0] o_exe_dnpc,
	output o_exe_id_bubble,
	output o_exe_exe_bubble,
	output o_exe_clint_trap

);
	reg EXE_valid;

	assign EXE_allow_in = !EXE_valid || EXE_ready_go && MEM_allow_in; //	MEMReg_allow_in;
	assign EXE_to_MEM_valid = EXE_valid && EXE_ready_go;

	always @(posedge clk)begin
	  if(rst)begin
	    EXE_valid <= 1'b0;
	  end
	  else if(EXE_allow_in)begin
	    EXE_valid <= ID_to_EXE_valid;
	  end
	end

	wire reg_w_en;
	assign o_exe_reg_w_en = reg_w_en;
	assign reg_w_en = ID_to_EXE_valid && EXE_allow_in;


	reg o_exe_lm_en_i;
	assign o_exe_lm_en = EXE_valid && o_exe_lm_en_i;

	reg o_exe_sm_en_i;
	assign o_exe_sm_en = EXE_valid && o_exe_sm_en_i;

	reg o_exe_w_en_i;
	assign o_exe_w_en = EXE_valid && o_exe_w_en_i;

//	reg [2:0] o_exe_RegWrite_en_i;
//	assign o_exe_RegWrite_en = EXE_valid && o_exe_RegWrite_en_i;

	reg [16:0] o_exe_alu_op_i;
	assign o_exe_alu_op = {17{EXE_valid}} & o_exe_alu_op_i;	

	Reg #(4,  4'b0001)  i0  (clk, rst || flush, i_exe_AluData1_en, o_exe_AluData1_en, reg_w_en); //for nop
	Reg #(7,  7'b00100)  i1  (clk, rst || flush, i_exe_AluData2_en, o_exe_AluData2_en, reg_w_en);
	Reg #(64, 64'b0) i2  (clk, rst || flush, i_exe_src1, o_exe_src1, reg_w_en);
	Reg #(64, 64'b0) i3  (clk, rst || flush, i_exe_src2, o_exe_src2, reg_w_en);
	Reg #(64, 64'b0) i4  (clk, rst || flush, i_exe_ext_imm, o_exe_ext_imm, reg_w_en);
	Reg #(64, 64'b0) i5  (clk, rst || flush, i_exe_pc_link, o_exe_pc_link, reg_w_en);
	Reg #(64, 64'b0) i6  (clk, rst || flush, i_exe_shamt, o_exe_shamt, reg_w_en);
	Reg #(17, 17'b1) i7  (clk, rst || flush, i_exe_alu_op, o_exe_alu_op_i, reg_w_en);
	Reg #(1,  1'b0)  i8  (clk, rst || flush, i_exe_word_en, o_exe_word_en, reg_w_en);
	Reg #(3,  3'b0)  i9  (clk, rst || flush, i_exe_funct3, o_exe_funct3, reg_w_en);
	Reg #(5,  5'b0)  i10 (clk, rst || flush, i_exe_rd, o_exe_rd, reg_w_en);
	Reg #(1,  1'b0)  i11 (clk, (rst || flush), i_exe_w_en, o_exe_w_en_i, reg_w_en);
	Reg #(1,  1'b0)  i12 (clk, (rst || flush), i_exe_lm_en, o_exe_lm_en_i, reg_w_en);
	Reg #(1,  1'b0)  i13 (clk, (rst || flush), i_exe_sm_en, o_exe_sm_en_i, reg_w_en);
	Reg #(4,  4'b0)  i14 (clk, (rst || flush), i_exe_RegWrite_en, o_exe_RegWrite_en, reg_w_en);
	Reg #(64, 64'b0) i19 (clk, (rst || flush), i_exe_csr_src1, o_exe_csr_src1, reg_w_en);
	
	//for difftest//
	Reg #(32, 32'h13)  i15 (clk, rst , i_exe_inst, o_exe_inst, reg_w_en);
	Reg #(64, 64'b0)  i16 (clk, rst ||flush, i_exe_dnpc, o_exe_dnpc, reg_w_en);
	Reg #(1,   1'b0)  i17 (clk, rst || flush, i_exe_id_bubble, o_exe_id_bubble, reg_w_en);
	Reg #(1,   1'b0)  i18 (clk, rst || flush, i_exe_exe_bubble && ID_to_EXE_valid, o_exe_exe_bubble, reg_w_en);
	Reg #(1,   1'b0)  i20 (clk, rst || flush, i_exe_clint_trap && ID_to_EXE_valid, o_exe_clint_trap, reg_w_en);
	
endmodule
